Java Blog

Since I'm very lazy in sharing my thoughts, this blog may contain very few posts - so please be patient! :-)

Freitag, Juni 05, 2009

Hibernate PreparedStatement Parameter Logging

Immer wieder ein Problem: wie überrede ich Hibernate, die Parameter auszugeben, die in die PreparedStatements eingesetzt werden?

Hibernate loggt mit log4j - also muss eigentlich nur ein entsprechender Log-Level gesetzt werden und man sieht die Log-Ausgaben.

Weit gefehlt, wenn man vermutet, dass folgendes Statement in der log4j.properties ausreicht:

logger.org.hibernate=DEBUG


Diese Einstellung loggt zwar ziemlich viel von Hibernate (u.a. die PreparedStatements, die Hibernate ausführt) und macht das System dann ziemlich langsam :o) - gibt aber nicht die gewünschten PreparedStatement-Parameter aus.
In vielen Foren weit verbreitet ist folgender Hinweis:

log4j.logger.org.hibernate.SQL=DEBUG


Diese Einstellung gibt ausschließlich die PreparedStatements aus und erspart somit den Rest des umfangreichen Hibernate-Loggings. Die Parameter für das PreparedStatement fehlen aber trotzdem.

Gestern ging ich dann ziemlich lange auf die Suche und fand dann irgenwann in einem Foren-Eintrag folgenden Hinweis:

log4j.logger.org.hibernate.type=TRACE


Wichtig ist hierbei wirklich der Hinweis auf TRACE, weil selbst in DEBUG nichts zu sehen ist...


log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE


Beide Einstellungen zusammen ermöglichen dann ein detailliertes Nachverfolgen der ausgeführten SQL-Statements:


DEBUG - {SQL} - select persistent0_.ID as ID8_, persistent0_.NAME as NAME8_, persistent0_.VERSION as VERSION8_, persistent0_.BUNDLE_COMMENT as BUNDLE4_8_, persistent0_.BUNDLE_DESCRIPTION as BUNDLE5_8_, persistent0_.TYPE as TYPE8_, persistent0_.CONTENT as CONTENT8_, persistent0_.VALID_FROM as VALID8_8_, persistent0_.VALID_TO as VALID9_8_, persistent0_.INSERTED_BY as INSERTED10_8_, persistent0_.INSERTED_AT as INSERTED11_8_, persistent0_.UPDATED_BY as UPDATED12_8_, persistent0_.UPDATED_AT as UPDATED13_8_ from rzanner.BRM_PERSISTENT_BUNDLE persistent0_ where persistent0_.NAME=? and persistent0_.VERSION=?
TRACE - {StringType} - binding 'blbb.samples.config' to parameter: 1
TRACE - {StringType} - binding '1.3.0.0-5-01-0-SNAPSHOT' to parameter: 2
TRACE - {LongType} - returning '112817' as column: ID8_
TRACE - {StringType} - returning 'blbb.samples.config' as column: NAME8_
TRACE - {StringType} - returning '1.3.0.0-5-01-0-SNAPSHOT' as column: VERSION8_
TRACE - {DateType} - returning '04 Juni 2009' as column: VALID8_8_
TRACE - {DateType} - returning null as column: VALID9_8_
TRACE - {StringType} - returning 'test:rzanner' as column: INSERTED10_8_
TRACE - {TimestampType} - returning '2009-06-04 16:36:08' as column: INSERTED11_8_
TRACE - {StringType} - returning null as column: UPDATED12_8_
TRACE - {TimestampType} - returning null as column: UPDATED13_8_

Labels:

Montag, Juli 21, 2008

Maven 2 "POM Inheritance" - Revisited

Ich habe die Lösung! Ein Kollege hat mich auf die Idee gebracht, doch nicht den How-Tos der ganzen Maven2-Büchern zu folgen :o) - also <version> und <groupId> aus dem Parent-POM in den Kind-POMs wieder zu verwenden.

Statt dessen trenne ich beide Versionierungen und definiere die Version des Parent-POM als konstant (z. B. "1") und hinterlege dort die eigentlichen Project-Artifact-Properties:

<project>
...
<groupId>test.group</groupId>
<artifactId>parent</artifactId>
<version>1</version>

<properties>
<project.artifact.groupId>test.group</project.artifact.groupId>
<project.artifact.version>1.0.0.2</project.artifact.version>
</properties>
...
</project>

In meinen Kind-POMs referenziere ich dann das Parent-POM mit dem <parent>-Tag und re-definiere aber <groupId> und <version> mit den im Parent-POM definierten Properties:

<project>
...
<parent>
<groupId>test.group</groupId>
<artifactId>parent</artifactId>
<version>1</version>
</parent>

<groupId>${project.artifact.groupId}</groupId>
<artifactId>child1</artifactId>
<version>${project.artifact.version}</version>
...
</project>

Dadurch habe ich zwar unterschiedliche Versionen des Parent-POM und des eigentlichen Projekts - muss aber trotzdem die Versionsnummer für ein neues Release meines Projekts nur an einer Stelle ändern - die Properties im Parent-POM.

Genau so, wie ich es haben wollte! Nur ein wenig anders... :o)

Labels: ,

Freitag, Juli 18, 2008

Maven 2 "POM Inheritance"

Ich beschäftige mich gerade mit Maven 2. In meiner Firma verwenden wir ein Maven 1 Buildsystem, das auch das Multiproject-Plug-In verwendet.

Die Projektstruktur sieht in etwa so aus:

ROOT/
project/
module-1/
project.properties
project.xml - <extend>../commons/project.xml</extend>
module-2/
project.properties
project.xml - <extend>../commons/project.xml</extend>
commons/
project.properties - definiert alle Dependency-Versionsnummern, aber auch
Version und Group-ID des gesamten Projekts
project.xml - definiert gemeinsame Dependencies
project.properties - Multi-Project-Konfigurations-Properties
project.xml - <extend>commons/project.xml</extend>

Das commons-Projekt enthält das "Parent-POM", welches sowohl die gemeinsamen Dependencies mit ihren Versionsnummern (ausgelagert in project.properties) als auch die Versionsnummer und Group-ID des gesamten Projekts - also die Vorgabe für alle Module - enthält.

Die Module selbst enthalten weder <groupId> noch <version>-Tags, sondern "erben" diese von dem commons/project.xml mittels <extend>-Tag ("POM Inheritance").

Damit werden Versionsnummer und Group-ID zentral über das commons-Projekt gesteuert und es muss bei einem neuen Release nur an dieser einen Stelle editiert werden.

Über die übergeordnete project.xml-Datei ist mittels multiproject-plugin ein Build des gesamten Projekt - also aller Module - möglich. In project.properties wird dabei mit Include- und Exclude-Patterns definiert, welche project.xml-Dateien der untergeordneten Module in den Mutiproject-Build einfließen sollen ("POM Aggregation").
Dabei wird z. B. das commons/project.xml exkludiert, da es ja nur das "Parent-POM" für alle anderen Module ist.

Mit Maven 2 ist alles ein wenig anders.

Es wird allerdings ebenfalls unterschieden in "POM Inheritance" und "POM Aggregation".

"POM Aggregation" ist einfach: das Top-Level-Projekt enthält in einer <modules>-Sektion alle Module, die gleichzeitig gebaut werden sollen - also voneinander abhängig sind.
Das war mit Maven 1 nur über ein zusätzliches Plug-In - maven-multiproject-plugin - möglich, während "POM Aggregation" bei Maven 2 nun integraler Bestandteil ist.

Mit "POM Inheritance", wie sie in Maven 2 implementiert ist, habe ich aber so meine Probleme.

Das "Parent POM" - in Maven 1 mittels <extend> als bloße Datei-Ressource definiert - wird nun über alle drei Projekt-Koordinaten referenziert: Group-ID, Artifact-ID und Version. Dafür darf dann in dem Kind-POM die Group-ID und die Version "fehlen" (siehe Beispiel).

<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.zanner.test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
</parent>
<artifactId>test-module</artifactId>
...
</project>

"Fehlen" tun die Angaben aber nicht wirklich: durch die Angabe in dem <parent>-Tag habe ich nun in jedem Modul-Projekt die Versionsnummer des Parent-POMs - und damit des gesamten Projekts - zu stehen und muss bei einem neuen Release alle Module-POMs anpassen.

Wo ist denn da die Wiederverwendung? Ich brauche zwar die Versionsnummer nicht im Modul-POM anzugeben, aber dafür die des Parent-POM, die dann vom Modul-POM wieder geerbt wird? Häh? Irgendwie fehlt mir hier ein Stück Verständnis.

Aber es ist schon spät und außerdem Wochenende - ich gehe lieber ins Bett :o) ...

Labels: ,

Dienstag, April 15, 2008

Wie bestimme ich das JAR einer Java-Klasse?

Vor kurzem hatte ich die Notwendigkeit, zur Laufzeit den Pfad zum JAR einer geladenen Java-Klasse zu erfahren und musste erfahren, dass es in Java hier erstaunlicherweise keinen Standardweg gibt. Na gut - Java ist bnun nicht die dynamischste Sprache, aber eine solche Funktionalität hätte ich schon erwartet - schließlich muss die JVM buzw. der ClassLoader ja auch wissen, woher er physisch seine Klassen holt bzw. geholt hat.

Als erstes bin ich auf die "ProtectionDomain - CodeSource"-Strategie gestoßen - in einem Artikel von Roedy Green's "Java Glossary" mit einem Code-Beispiel hinterlegt.

Für die meisten Fälle scheint das auch zu funktionieren, obwohl es nun überhaupt nichts mit dem der Klasse zugrunde liegenden JAR zu tun hat, sondern offenbar eher ein Standardverhalten der JVM ausnutzt.

Unglücklicherweise funktioniert das beschriebene Verfahren auch nicht immer. Problematisch wird es nämlich genau dann, wenn eine Bibliothek "Schweinereien" mit dem ClassLoader bzw. dem Security-Mechanismus von Java macht.
Maven 1.1 scheint so ein Fall zu sein. Beim Laufenlassen der JUnit-Tests eines Maven-1.1-Projekts nämlich zeigten alle CodeSource-Referenzen immer auf das erste JAR im MAVEN_HOME/lib-Verzeichnis: ant-1.6.5.jar.

Nach weiterer intensiver Forschung stieß ein Kollege von mir auf eine weitere - eigentlich viel näher liegende - Lösung für das Problem "JAR zu einer Klasse".
Im Blog von Nirav Thaker steht eine Lösung beschrieben, die mit Standard-Java-Mitteln arbeitet und eine JarURLConnection benutzt, um den Pfad zu dem JAR einer Klasse bestimmt. Für die Eiligen hier schnell der Quellcode:

public static URL getJarURL(Class clazz) {
String classResource = "/" + clazz.getPackage().getName().replace('.', '/')
+ "/" + clazz.getSimpleName() + ".class";
URL clsUrl = clazz.getResource(classResource);
if (clsUrl != null) {
try {
URLConnection conn = clsUrl.openConnection();
if (conn instanceof JarURLConnection) {
JarURLConnection connection = (JarURLConnection) conn;
return connection.getJarFileURL();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return null;
}

Im Gegensatz zu der bei Nirav veröffentlichten Version funktioniert diese Methode hier auch bei Klassen, die nicht im Default-Package liegen :o)...

Labels: ,

Freitag, Juni 15, 2007

WidgetServer

Anwendungsentwicklung der nächsten Generation

Während eines früheren Projekts hatte ich bereits Kontakt mit dem WidgetServer. Er umfasst hauptsächlich ein OpenSource Framework für die Anwendungsentwicklung in Java.

Ich habe den letzten Satz absichtlich so neutral wie möglich formuliert, da der WidgetServer eben KEIN übliches Framework für die Entwicklung von Webanwendungen ist. Im Gegensatz zu Frameworks wie Echo oder JSF beschränkt sich nämlich WidgetServer nicht auf den Kanal "HTML", sondern kann mit seinen GUI-Plattformneutralität auch Swing-GUIs bedienen.

Doch beginnen wir ganz von vorn.

Bei meinem aktuellen Arbeitgeber besteht der Bedarf an der schnellen Entwicklung einer webbasierten Administrationsoberfläche für relativ komplexe geschäftslogische Prozesse. Die Konzepte dafür sind natürlich von der Fachseite schnell geschrieben, aber was meist das Hauptproblem darstellt, ist entweder fehlendes oder "zu kreatives" GUI-Design.

Für beides bietet sich mit dem WidgetServer eine hervorragende Plattform für das Prototyping - durch die Definition der GUI in einem XML-Format lässt sich sehr schnell eine Oberfläche zaubern, die Änderungen an der XML-Datei on-the-fly umsetzt und daher wirklich "Rapid" Prototyping ermöglicht.
WidgetServer selbst ist bereits ein stark gereiftes Framework - mittlerweile liegt die Version 1.6.1 vor und dementsprechend mächtig sind die vorhandenen GUI-Komponenten und ihre Funktionalität.

Schon lange bevor der Begriff "AJAX" geprägt wurde, bot WidgetServer bereits für den HTML-Kanal das partielle Rendering an. Auch dies ist ein Grund für die sehr funktionalen Webanwendungen, die sich mit diesem Framework entwickeln lassen.

Der größte Charme des Frameworks liegt aber meines Erachtens darin, dass die serverseitige Programmierung komplette Java-Entwicklung ist und rein gar nichts mit HTML oder HTTP zu tun hat.

Ein Beispiel

Ich brauche einen Button, also füge ich ein XML-Fragment in meine Anwendungsdefinition ein:
<button value="Tu was sinnvolles!" />
So ein Button hat natürlich irgendwie wenig Sinn ohne entsprechende Funktionalität dahinter. Also schreibe ich mir eine kleine Listener-Klasse, die ich per XML mit diesem Button assoziiere:
<button value="Tu was Sinnvolles!">
<srvlistener class="de.zanner.wiser.listener.DoButtonListener" />
</button>
Hier die Listener-Klasse:
package de.zanner.wiser.listener;

// add imports

public class DoButtonListener implements IUnGuiEventListener {

public void pcmf_execListener(UnComponent component) {
// TODO call business logic, modify component tree, ...
}

}
Wie man an diesem Beispiel bereits erkennt, ist das API etwas gewöhnungsbedürftig: es gibt natürlich keine "Un"-Komponente als undiszipliniertes Pendant einer Komponente ;o) .
Jedes API-Element (Klasse, Interface oder Methode) besitzt einen Präfix, der mehr über den Typen des entsprechenden Artefakts aussagt.
Im Fall der "UnComponent" steht das Präfix für "Unified" und bezeichnet damit eine ganze Reihe von Basisklassen, die gemeinsame Funktionalität sowohl für den Markup- (HTML-) als auch für den Swing-Kanal enthalten.
Analog dazu gibt es noch Präfixe wie "Ke" für "Kernel" für noch allgemeinere Basiklassen ohne Bezug zur GUI oder die Präfixe "Mu" und "Ho" für die kanalspezifischen API-Klassen für die Kanäle "Markup" und "HalfObject".

Am Präfix "Ho" für "HalfObject" erkennbar ist die Verwandschaft des Swing-Kanals zu Frameworks wie "ULC" - dem Ultra Light Client von Canoo oder Nexaweb. Über diesen Kanal kann ich aber wenig Auskunft erteilen, da ich mich momentan nur mit dem HTML-Kanal befasse.

Markup

Hier also etwas mehr Infos über den Markup-Kanal, der üblicherweise für browserbasierte Webanwendungen verwendet wird.

Einfluss auf das Aussehen der einzelnen Komponenten kann über Template-Dateien genommen werden, die von Renderer-Klassen dazu verwendet werden, die Komponente zusammenzubauen.
Hier wird auch ersichtlich, warum der Kanal "Markup" und nicht etwa "HTML" heißt - es kann in dem Template natürlich beliebiger Markup-Code enthalten sein. Mit dem passenden Renderer dazu kann dann beispielsweise anstelle von HTML WML gerendert werden.
Lieferbestandteil ist ein kompletter HTML-Kanal für den InternetExplorer und Gecko-basierte Browser (Mozilla).

Entwicklung neuer Komponenten

Neue Komponenten können also recht einfach über ein eigenes Template und eine neue zugehörige Rendererklasse erstellt werden.
Die Assoziation von Renderer und Template geschieht in einer XML-Konfigurationsdatei, so dass das Erstellen neuer Komponenten auch über die Abwandlung bestehender Templates und Verwendung des bestehenden Renderers möglich ist, z. B., um einen Tabellenkopf anders zu gestalten als in der Standardtabelle vom WidgetServer.

Fazit

Der Fokus des WidgetServer liegt eindeutig auf Produktivität - ein ganz klarer Pluspunkt. Standards wie AJAX über XMLHTTPRequest findet man hier allerdings wenig.
Einziger Berührungspunkt mit der Servlet API ist z. B. das Servlet zur Kommunikation zwischen JavaScript-Bibliothek und WidgetServer.

Der Einstieg in die Entwicklung mit dem WidgetServer ist nicht ganz intuitiv.
Es gibt z. B. (noch) kein XML-Schema für die XML-Datei, welche die Anwendung definiert.
Etwas Abhilfe schafft hier der mit gelieferte GUI-Builder, der auch Doku zu den einzelnen Attributen liefert, aber leider dem aktuellen Release immer um 1 bis 2 Versionen hinterher läuft.

Der Aufbau der API ist zwar in sich logisch - aber erst, wenn man die Logik einmal verstanden hat ;o)...
Das aktuelle Geschäftsmodell der Firma C1 SetCon, für die der Entwickler des WidgetServer (Dirk von der Weiden) mittlerweile tätig ist, sieht daher ein "Startup Consulting" vor, das den Anwender in die Lage versetzen soll, selbst mit dem WidgetServer zu entwickeln.

Für meine Begriffe sind die üblichen 10 Tage für bereits vorbelastete GUI-Entwickler etwas zu hoch gegriffen. Wer darüber hinaus noch Erfahrung in der Swing-Programmierung hat, findet sich wirklich schnell zurecht, wenn die größte Einstiegshürde "GUI-Definition in XML" überwunden ist.

Für die Entwicklung von Anwendungen mit Kundenkontakt ist eine WidgetServer-Anwendung zu wenig an die Bedürnisse modernen Screen-Designs anpassbar. Für jedes neue Projekt ein neues Template-Kit zu schreiben ist mit Sicherheit zu aufwändig.
Für interne Anwendungen, bei denen es keine Beschränkungen hinsichtlich JavaScript gibt und die dann meist auch den Anspruch an hohe Interaktivität und desktopanwendungsähnliches Look-and-Feel haben, ist diese Lösung einer klassischen Webentwicklung mit Struts oder JSF haushoch überlegen.

Leider hat der WidgetServer etwas zu wenig sichtbare Community, was sicherlich einige potenzielle Anwender abschreckt.
Das liegt wahrscheinlich daran, dass der Dirk von der Weiden in Consulting-Projekte eingebunden ist und daher wenig Zeit bleibt, eine Community zu pflegen. Das ist auch der Grund, warum die Sourceforge- und java.net-Seiten etwas vernachlässigt werden.
C1 SetCon - speziell der Hauptentwickler Dirk von der Weiden - tut aber sehr viel dafür, die Wünsche und Bedürfnisse der Anwender umzusetzen und zu befriedigen.
Ein weiterer WidgetServer-Entwickler - Thomas Boshell - hat ein eigenes (englischsprachiges) Blog mit einer Kategorie zum WidgetServer.

Ich hoffe, dass durch mein Blog der WidgetServer etwas bekannter wird. Zumindest in Deutschland sollte er leicht Verbreitung finden, da die dahinter stehende Firma eine deutsche ist.
An alle, die angesichts eines deutschen Software-Produkts die Nase rümpfen: ein gutes Framework zur Webanwendungsentwicklung muss nicht aus den USA oder dem Ostblock kommen ;o) !

Labels:

Freitag, Juni 01, 2007

"Beyond Java" (Bruce A. Tate)

Ohne einen Anspruch auf ein fundiertes Literatur-Review hier mal mein erster Versuch einer Buchbesprechung. Ein Kollege, der im übrigen ziemlich fit in Java und Software-Architektur ist, hat mir obiges Buch ans Herz gelegt.

Im großen und ganzen enthält es Meinungen verschiedener bekannter Java-Entwickler über den aktuellen Stand und die Zukunft von Java als Programmiersprache. Kurze Essenz: Java sei als Programmiersprache für die normale Webanwendungsentwicklung zu komplex geworden. Statt dessen sollte für den Standard Anwendungsentwicklungsfall "Webanwendung auf Datenbank" über Alternativen nachgedacht werden. Es geht also um die Betrachtung potenzieller Nachfolgekandidaten für Java - aber nur in diesem begrenzten Szenario.
Dass dabei Ruby - insbesondere in Verbindung mit dem Webanwendungs-Framework Rails - nicht fehlen darf und sogar die Motivation zu diesem Buch darstellt, ist angesichts des aktuellen Hypes um diese in Japan enstandene Programmiersprache nicht verwunderlich.

Ich war ja etwas skeptisch. Bei neuen Programmiersprachen sowieso. Wahrscheinlich nicht gerade die besten Voraussetzungen für meine persönliche Weiterentwicklung. Aber wenn mich etwas Neues überzeugt (bzw. jemand anderes von etwas Neuem überzeugt ;o) ), kann ich es auch sehr schnell umsetzen und weiter geben. Auch wenn ich schon einiges über Ruby gelesen habe, hat mich daher erst der Hinweis von meinem Kollegen dazu animiert, mich überhaupt erst mit Ruby zu befassen.

Der Autor ist vorher bereits durch das Buch "Better, Faster, Lighter Java" in Erscheinung getreten und daher auch kein unbeschriebenes Blatt, was die Beurteilung von Java-Features angeht. Seine Meinung von Java ist stark geprägt von einer sehr großen Erfahrung im Consulting im Bereich Java-Anwendungsentwicklung. Ihm kann man in Sachen Java also keine mangelnde Fachkompetenz unterstellen.
Außerdem dringt aus jeder Zeile eine große Leidenschaft für Java hervor - er versucht also nicht, Java schlecht zu machen, sondern zeigt ziemlich objektiv die Schwächen von Java im Bereich Anwendungsentwicklung auf.

Als größte Schwäche kommt hier m. E. zum Tragen, dass der Fokus von Java und dem zugehörigen JCP sich immer mehr in Richtung serverseitige Programmierung verschoben hat. Die Produktivität im Bereich Anwendungsentwicklung hingegen ist durch die Komplexität der APIs und der Fülle an benötigten Frameworks aber immer weiter gesunken.

Produktivität bei der Anwendungsentwicklung sei aber heute das Maß der Dinge im schnelllebigen Internet-Markt und Java hat hier seiner Meinung nach den Anschluss verloren.

Aus den aufgestellten Schwächen der aktuellen Java 5 Version heraus abgeleitet stellt er eine Liste von Kriterien auf, die ein potenzieller Java-Nachfolger in diesem Bereich haben sollte. Dabei werden Konzepte wie Static/Dynamic Typing oder Strong/Weak Typing, Closures, Continuations usw. beleuchtet.
Int3eressanteweise geht er gerade mit den Features von Java, die in die neue version Einzug gehalten haben, um Java für die Zukunft zu rüsten (Generics, Auto-boxing) ziemlich hart ins Gericht - was man aber letzten Endes durch seine immer sehr guten Begründungen relativ schnell nachvollziehen kann.

Das ganze Buch ist gespickt mit Interviews mit aktuellen oder ehemaligen Java-Experten, über die man auch sehr viele Hintergrundinformationen zu Java und dem aktuellen Entwicklungsprozess sowohl in der Java- als auch speziell der Webanwendungsentwicklungs-Community erhält.

Ich bin ja seit meinem Kontakt mit der JSF-Spezifikation sowieso ein wenig ein gebranntes Kind, was den Java Community Process angeht. Aus meiner Sicht entstehen hier überwiegend von der Software-Industrie getriebene Kompromisse auf Kosten der Bedürfnisse des Markts geschlossen.

Das Buch ist also auch zur Erweiterung des eigenen Horizonts eine interessante Lektüre - mir hat sie an einigen Stellen die Augen geöffnet.
Außerdem ist das Buch nicht sehr dick und liest sich daher an einigen Tagen durch. Bei mir stauben die sonst üblichen 400+ Seiten Wälzer immer ungelesen ein - dieses Buch habe ich von der ersten bis zur letzten Seite verschlungen!

Labels: ,

Freitag, März 30, 2007

Eclipse WTP, JSF und JBoss

Heute mal ein klein wenig Ärger über Eclipse WTP. Offenbar verwendet das Web Tools Project von Eclipse den Projektnamen als Präfix für die jeweilige Deployment-Einheit, also bei einem Projektnamen von "JSF - Übung 01" würde beispielsweise das Web-Archiv "JSF - Übung 01.war" heißen. Dass damit nicht alle Application-Server klarkommen, kann man nicht nur vermuten...

Nun ja - während eine Tomcat 5.0-Runtime keine Probleme damit hat, verschluckt sich sowohl Tomcat 5.5 als auch ein JBoss 4.0.5 (der ja auch nur einen Tomcat 5.5 unter der Haube hat)
- das allerdings mit einer sehr "aussagekräftigen" Fehlermeldung:

java.lang.NullPointerException
javax.faces.webapp.FacesServlet.init(FacesServlet.java:165)


Der Code an der Stelle greift während der Servlet-Initialisierung auf die LifecycleFactory zu:

lifecycle = lifecycleFactory.getLifecycle(lifecycleId);


Auch nicht besonders hilfreich beim Finden des eigentlichen Fehlers.

Nun ja - in diesem Thread im JSF-Forum von SUN fand ich einen Hinweis auf Spaces im Dateinamen und überprüfte diesen Verdacht.
Siehe da - er bestätigte sich und nach Behebung dieses "Bugs" in meinem Projektnamen funktionierte es auch unter JBoss und Tomcat 5.5...

Labels: